package com.sylli.oeuf.server;

import java.util.ArrayList;
import java.util.Collection;

import com.sylli.oeuf.server.db.DatabaseProviderBundle;
import com.sylli.oeuf.server.db.sql.Generator;
import com.sylli.oeuf.server.exception.BasedException;
import com.sylli.oeuf.server.game.logic.ActionProduct;
import com.sylli.oeuf.server.game.logic.Battle;
import com.sylli.oeuf.server.game.logic.BattleActor;
import com.sylli.oeuf.server.game.logic.CastingTarget;
import com.sylli.oeuf.server.game.logic.DeBuff;
import com.sylli.oeuf.server.game.logic.EventParameter;
import com.sylli.oeuf.server.game.logic.Skill;
import com.sylli.oeuf.server.game.logic.action.ActionAddDebuff;
import com.sylli.oeuf.server.game.logic.action.CombatLog;
import com.sylli.oeuf.server.game.logic.action.Damage;
import com.sylli.oeuf.server.game.logic.action.ActionValue.ActionValueElement;
import com.sylli.oeuf.server.game.logic.action.ActionValue.ActionValueFlag;
import com.sylli.oeuf.server.game.logic.invocation.InvocationAction;
import com.sylli.oeuf.server.game.logic.invocation.InvocationEntry;
import com.sylli.oeuf.server.game.logic.invocation.InvocationEvent;
import com.sylli.oeuf.server.object.transferable.CharacterGeneralInfoTO;
import com.sylli.oeuf.server.object.transferable.CharacterPostDataTO;
import com.sylli.oeuf.server.object.transferable.MonsterTO;
import com.sylli.oeuf.server.object.transferable.PostBattleResponseTO;
import com.sylli.oeuf.server.object.transferable.StatTO;
import com.sylli.oeuf.server.object.transferable.WrappedCharacterInfoTO;

public class SimpleJavaAppWithMain {

	public static void main(String[] str) {
		SimpleJavaAppWithMain sjapp = new SimpleJavaAppWithMain();
		Generator gap_gen = new Generator();
		try {
			// sjapp.generateSkill();
			// sjapp.eye();
			// sjapp.fix();
			// sjapp.testEngineReferenceProblem();
			// sjapp.testSimplestScenario();
			// sjapp.testInstall();
			// sjapp.testEngine();
			// sjapp.testSkillSystem();
			// gap_gen.execute();
			Damage dmg = new Damage(null, null, 30, ActionValueFlag.Critical, ActionValueElement.Arcane);
			CombatLog cl = new CombatLog(null, null, "Hello %s", dmg);
			System.out.println("+ " + cl.get());
			dmg.setValue(3000);
			dmg.setFlag(ActionValueFlag.Normal);
			System.out.println("+ " + cl.get());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private void fix() throws BasedException {
		MonsterTO mon = providers.monster.get("name = 'lunatic'");
		
		CharacterGeneralInfoTO cha = providers.charGenInfo.get("name = 'haloowing'");
		CharacterPostDataTO po = providers.charPostData.get("char_id = '" + cha.getCharId() + "'");
		
		WrappedCharacterInfoTO wc = new WrappedCharacterInfoTO(cha, po);
		
		BattleActor player = new BattleActor(wc);
		BattleActor monst = new BattleActor(mon);
		
		player.setUsingPlan(wc.findPlan(1));
		
		Battle b = new Battle(player, monst);
		
		PostBattleResponseTO pbrt = new PostBattleResponseTO();
		b.startBattle(pbrt);
		
	}

	public void testSkillSystem() {
		
		MonsterTO mob = __createMonster();
		WrappedCharacterInfoTO player = __createPlayer();
		
		Battle b = new Battle(new BattleActor(player), new BattleActor(mob));

		PostBattleResponseTO post = new PostBattleResponseTO();
		b.startBattle(post);
		
		for (String s : post.getLog()) {
			System.out.println("S: " + s);
		}
		
	}
	
	public void testScriptlessSkillSystem() {
		// try create skill
		Skill normal_attack = new Skill("attack", CastingTarget.FocusTarget);
		Skill simple_dot_applier = new Skill("rend", CastingTarget.FocusTarget);
		final DeBuff simple_dot = new DeBuff("rend_tick", 3);
		normal_attack
				.getEntries()
				.put(
						InvocationEvent.STD_IE_ON_ACTIVE,
						new InvocationEntry(
								com.sylli.oeuf.server.game.logic.invocation.InvocationCondition.ALWAYS_TRUE_IC,
								new InvocationAction() {
									@Override
									public Collection<ActionProduct> act(
											int rank, BattleActor caster,
											CastingTarget target,
											EventParameter param) {

										Collection<ActionProduct> product = new ArrayList<ActionProduct>();
										product.add(new Damage(caster, 
												caster.getProperTarget(target),
												caster.getMaxDmg(),
												ActionValueFlag.Normal,
												ActionValueElement.Physical));
										return product;
									}
								}));

		simple_dot_applier
				.getEntries()
				.put(
						InvocationEvent.STD_IE_ON_ACTIVE,
						new InvocationEntry(
								com.sylli.oeuf.server.game.logic.invocation.InvocationCondition.ALWAYS_TRUE_IC,
								new InvocationAction() {

									@Override
									public Collection<ActionProduct> act(
											int rank, BattleActor caster,
											CastingTarget target,
											EventParameter param) {

										Collection<ActionProduct> product = new ArrayList<ActionProduct>();
										product.add(new ActionAddDebuff(caster,
												caster.getProperTarget(target), 
												simple_dot));
										return product;
									}
								}));

		simple_dot
				.getEntries()
				.put(
						InvocationEvent.STD_IE_ON_TICK,
						new InvocationEntry(
								com.sylli.oeuf.server.game.logic.invocation.InvocationCondition.ALWAYS_TRUE_IC,
								new InvocationAction() {

									@Override
									public Collection<ActionProduct> act(
											int rank, BattleActor caster,
											CastingTarget target,
											EventParameter param) {

										Collection<ActionProduct> product = new ArrayList<ActionProduct>();
										product.add(new Damage(caster, 
												caster.getProperTarget(target),
												caster.getMinDmg(),
												ActionValueFlag.Normal,
												ActionValueElement.Physical));

										return product;
									}
								}));
	}

	DatabaseProviderBundle providers = DatabaseProviderBundle.getInstance();

	public void eye() {
		try {
			CharacterGeneralInfoTO o = providers.charGenInfo
					.get("name = 'haloowing'");
			System.out.println("o=" + o);
		} catch (BasedException e) {
			e.printStackTrace();
		}
	}

	public MonsterTO __createMonster() {
		MonsterTO mob2 = new MonsterTO();
		mob2.setName("chocobo");
		mob2.setMonsterId(0);
		mob2.setLevel(33);
		mob2.setStat(new StatTO(30, 7, 55, 20, 12, 11, 2, 22, 2, 2));
		mob2.setStatHp(2000);
		mob2.setStatMp(10);

		return mob2;
	}

	public WrappedCharacterInfoTO __createPlayer() {
		CharacterGeneralInfoTO genInf = new CharacterGeneralInfoTO();
		genInf.setAccountId(0);
		genInf.setCharId(0);
		genInf.setClazzId(0);
		genInf.setLevel(3);
		genInf.setMaxExp(300);
		genInf.setMaxHp(300);
		genInf.setMaxMp(120);
		genInf.setName("Ninekaw");
		genInf.setStat(new StatTO(30, 2, 2, 2, 2, 2, 2, 22, 2, 2));
		CharacterPostDataTO post = new CharacterPostDataTO();
		post.setCharId(0);
		post.setCurrentExp(150);
		post.setCurrentHp(180);
		post.setCurrentMp(120);
		post.setCurrentMap(0);
		post.setCurrentPos(0);
		WrappedCharacterInfoTO p = new WrappedCharacterInfoTO(genInf, post);
		return p;
	}
}
